/*
 * data_io.cpp
 * 串口调试工具 - 数据IO管理模块源文件
 * 
 * 此文件包含DataIO类的实现，负责数据收发和格式化功能。
 */

#include "data_io.h"
#include <QDateTime>
#include <QRegularExpression>
#include <QScrollBar>
#include <QTextEdit>
#include <QDebug>
#include <QFile>
#include <QTextStream>

// 构造函数实现
DataIO::DataIO(QSerialPort *serialPort, QObject *parent) : QObject(parent)
{
    // 设置串口指针
    this->serialPort = serialPort;
    
    // 初始化状态标志
    isHexSend = false;
    isHexReceive = false;
    isTimestampEnabled = false;
    isAutoScrollEnabled = true;
    isAutoSend = false;
    pauseReceiving = false;
    
    // 初始化计数器
    sentBytesCount = 0;
    receivedBytesCount = 0;
    
    // 初始化速率计算相关变量
    lastStatsUpdateTime = QDateTime::currentDateTime();
    lastReceivedBytesSnapshot = 0;
    
    // 初始化最大保留行数
    maxRetainedLines = 10000;
    
    // 初始化自动发送定时器
    autoSendTimer = new QTimer(this);
    connect(autoSendTimer, &QTimer::timeout, this, &DataIO::onAutoSendTimerTimeout);
    autoSendTimer->setInterval(1000); // 默认1秒
    
    // 初始化接收刷新定时器
    receiveFlushTimer = new QTimer(this);
    connect(receiveFlushTimer, &QTimer::timeout, this, &DataIO::onReceiveFlushTimerTimeout);
    receiveFlushTimer->setInterval(100); // 默认100ms刷新一次
    
    // 连接串口的readyRead信号
    if (serialPort) {
        connect(serialPort, &QSerialPort::readyRead, this, &DataIO::readSerialData);
    }
}

// 析构函数实现
DataIO::~DataIO()
{
    // 停止定时器
    autoSendTimer->stop();
    receiveFlushTimer->stop();
    
    // 清理资源
    delete autoSendTimer;
    delete receiveFlushTimer;
}

// 读取串口数据
void DataIO::readSerialData()
{
    if (!serialPort || !serialPort->isOpen()) {
        return;
    }
    
    // 读取所有可用数据
    QByteArray data = serialPort->readAll();
    
    if (data.isEmpty()) {
        return;
    }
    
    // 增加接收字节计数
    receivedBytesCount += data.size();
    
    // 创建接收数据块
    ReceiveDataBlock dataBlock;
    dataBlock.rawData = data;
    
    // 添加时间戳（如果启用）
    if (isTimestampEnabled) {
        dataBlock.timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz");
    }
    
    // 检查是否需要前置换行符
    dataBlock.prependNewLine = false;
    if (!receiveDataBlocks.isEmpty()) {
        const ReceiveDataBlock &lastBlock = receiveDataBlocks.last();
        // 如果前一个数据块以换行符结束，则不需要前置换行符
        if (!lastBlock.rawData.isEmpty() && lastBlock.rawData.endsWith('\n')) {
            dataBlock.prependNewLine = true;
        }
    }
    
    // 添加到接收数据块列表
    receiveDataBlocks.append(dataBlock);
    
    // 如果没有暂停接收，则格式化并显示数据
    if (!pauseReceiving) {
        // 如果启用了定时批量刷新，则只在定时器触发时刷新UI
        // 否则立即刷新UI
        if (!receiveFlushTimer->isActive()) {
            flushReceiveBuffer();
        } else {
            // 如果缓冲行数过多，立即刷新以避免内存占用过大
            if (receiveBufferLines.size() > 100) {
                flushReceiveBuffer();
            }
        }
    }
    
    // 发出接收数据信号
    emit dataReceived(data.size());
}

// 发送数据到串口
bool DataIO::sendData(const QByteArray &data)
{
    if (!serialPort || !serialPort->isOpen()) {
        return false;
    }
    
    // 写入数据
    qint64 bytesWritten = serialPort->write(data);
    
    if (bytesWritten > 0) {
        // 增加发送字节计数
        sentBytesCount += bytesWritten;
        
        // 发出数据发送信号
        emit dataSent(bytesWritten);
        
        return true;
    }
    
    return false;
}

// 根据输入文本和格式发送数据
bool DataIO::sendData(const QString &inputText, bool isHex)
{
    // 解析输入数据
    QByteArray data = parseDataFromInput(inputText, isHex);
    
    // 发送解析后的数据
    return sendData(data);
}

// 格式化数据用于显示
QString DataIO::formatDataForDisplay(const QByteArray &data, bool isHex)
{
    if (data.isEmpty()) {
        return QString();
    }
    
    QString formattedText;
    
    if (isHex) {
        // 十六进制格式显示
        formattedText = data.toHex(' ');
    } else {
        // ASCII格式显示
        formattedText = QString::fromUtf8(data);
    }
    
    return formattedText;
}

// 从输入解析数据
QByteArray DataIO::parseDataFromInput(const QString &input, bool isHex)
{
    QByteArray result;
    
    if (isHex) {
        // 十六进制格式解析
        // 移除所有非十六进制字符和空格
        QString hexStr = input;
        hexStr.remove(QRegularExpression("[^0-9a-fA-F]"));
        
        // 确保字符串长度为偶数
        if (hexStr.length() % 2 != 0) {
            hexStr += "0";
        }
        
        // 解析每两个字符为一个字节
        for (int i = 0; i < hexStr.length(); i += 2) {
            QString byteStr = hexStr.mid(i, 2);
            bool ok;
            uchar byte = byteStr.toUInt(&ok, 16);
            if (ok) {
                result.append(byte);
            }
        }
    } else {
        // ASCII格式解析
        // 处理转义字符
        QString processedInput = input;
        
        // 处理\r、\n、\t等转义序列
        processedInput.replace("\\r", "\r");
        processedInput.replace("\\n", "\n");
        processedInput.replace("\\t", "\t");
        processedInput.replace("\\\"", "\"");
        
        result = processedInput.toUtf8();
    }
    
    return result;
}

// 批量刷新接收缓冲区到UI
void DataIO::flushReceiveBuffer()
{
    if (receiveDataBlocks.isEmpty()) {
        return;
    }
    
    QStringList newLines;
    
    // 处理所有接收数据块
    for (const ReceiveDataBlock &block : receiveDataBlocks) {
        QString formattedLine;
        
        // 添加时间戳（如果启用）
        if (isTimestampEnabled && !block.timestamp.isEmpty()) {
            if (block.prependNewLine) {
                formattedLine += "\n[" + block.timestamp + "] " + formatDataForDisplay(block.rawData, isHexReceive);
            } else {
                formattedLine += "[" + block.timestamp + "] " + formatDataForDisplay(block.rawData, isHexReceive);
            }
        } else {
            if (block.prependNewLine) {
                formattedLine += "\n" + formatDataForDisplay(block.rawData, isHexReceive);
            } else {
                formattedLine += formatDataForDisplay(block.rawData, isHexReceive);
            }
        }
        
        // 分割为多行并添加到行缓冲
        newLines.append(formattedLine.split('\n'));
    }
    
    // 清空数据块列表
    receiveDataBlocks.clear();
    
    // 添加新行到行缓冲
    receiveBufferLines.append(newLines);
    
    // 限制行缓冲大小
    enforceMaxLines();
    
    // 发出需要更新UI的信号
    emit receiveBufferReady(receiveBufferLines);
}

// 强制限制最大行数
void DataIO::enforceMaxLines()
{
    if (receiveBufferLines.size() > maxRetainedLines) {
        // 移除最旧的行
        int linesToRemove = receiveBufferLines.size() - maxRetainedLines;
        receiveBufferLines.remove(0, linesToRemove);
    }
}

// 重新格式化并重显示所有数据
void DataIO::reformatAndRedisplayData()
{
    // 从原始数据块重新格式化
    receiveBufferLines.clear();
    
    for (const ReceiveDataBlock &block : receiveDataBlocks) {
        QString formattedLine;
        
        // 添加时间戳（如果启用）
        if (isTimestampEnabled && !block.timestamp.isEmpty()) {
            if (block.prependNewLine) {
                formattedLine += "\n[" + block.timestamp + "] " + formatDataForDisplay(block.rawData, isHexReceive);
            } else {
                formattedLine += "[" + block.timestamp + "] " + formatDataForDisplay(block.rawData, isHexReceive);
            }
        } else {
            if (block.prependNewLine) {
                formattedLine += "\n" + formatDataForDisplay(block.rawData, isHexReceive);
            } else {
                formattedLine += formatDataForDisplay(block.rawData, isHexReceive);
            }
        }
        
        receiveBufferLines.append(formattedLine.split('\n'));
    }
    
    // 强制限制最大行数
    enforceMaxLines();
    
    // 发出需要更新UI的信号
    emit receiveBufferReady(receiveBufferLines);
}

// 清空接收缓冲区
void DataIO::clearReceiveBuffer()
{
    receiveDataBlocks.clear();
    receiveBufferLines.clear();
    
    // 发出清空信号
    emit receiveBufferCleared();
}

// 设置自动发送状态
void DataIO::setAutoSendEnabled(bool enabled)
{
    isAutoSend = enabled;
    
    if (enabled) {
        // 启动自动发送定时器
        autoSendTimer->start();
    } else {
        // 停止自动发送定时器
        autoSendTimer->stop();
    }
}

// 设置自动发送间隔
void DataIO::setAutoSendInterval(int interval)
{
    autoSendTimer->setInterval(interval);
}

// 设置十六进制发送模式
void DataIO::setHexSendEnabled(bool enabled)
{
    isHexSend = enabled;
}

// 设置十六进制接收模式
void DataIO::setHexReceiveEnabled(bool enabled)
{
    isHexReceive = enabled;
    
    // 如果已经有接收的数据，重新格式化并重显示
    if (!receiveDataBlocks.isEmpty()) {
        reformatAndRedisplayData();
    }
}

// 设置时间戳启用状态
void DataIO::setTimestampEnabled(bool enabled)
{
    isTimestampEnabled = enabled;
}

// 设置自动滚动启用状态
void DataIO::setAutoScrollEnabled(bool enabled)
{
    isAutoScrollEnabled = enabled;
}

// 设置暂停接收状态
void DataIO::setPauseReceiving(bool paused)
{
    pauseReceiving = paused;
    
    // 如果恢复接收，则立即刷新缓冲区
    if (!paused && !receiveDataBlocks.isEmpty()) {
        flushReceiveBuffer();
    }
}

// 设置最大保留行数
void DataIO::setMaxRetainedLines(int maxLines)
{
    maxRetainedLines = maxLines;
    enforceMaxLines();
}

// 获取统计信息
DataStatistics DataIO::getStatistics() const
{
    DataStatistics stats;
    stats.sentBytes = sentBytesCount;
    stats.receivedBytes = receivedBytesCount;
    
    // 计算接收速率
    QDateTime currentTime = QDateTime::currentDateTime();
    int elapsedMs = lastStatsUpdateTime.msecsTo(currentTime);
    
    if (elapsedMs > 0) {
        quint64 bytesReceivedSinceLastUpdate = receivedBytesCount - lastReceivedBytesSnapshot;
        stats.receiveRate = (bytesReceivedSinceLastUpdate * 1000.0) / elapsedMs;
    } else {
        stats.receiveRate = 0;
    }
    
    return stats;
}

quint64 DataIO::getReceivedBytesCount() const
{
    return receivedBytesCount;
}

quint64 DataIO::getSentBytesCount() const
{
    return sentBytesCount;
}

double DataIO::getCurrentReceiveRate() const
{
    QDateTime currentTime = QDateTime::currentDateTime();
    int elapsedMs = lastStatsUpdateTime.msecsTo(currentTime);
    if (elapsedMs <= 0) {
        return 0.0;
    }
    quint64 bytesReceivedSinceLastUpdate = receivedBytesCount - lastReceivedBytesSnapshot;
    return (bytesReceivedSinceLastUpdate * 1000.0) / elapsedMs;
}

// 清空统计信息
void DataIO::clearStatistics()
{
    sentBytesCount = 0;
    receivedBytesCount = 0;
    lastReceivedBytesSnapshot = 0;
    lastStatsUpdateTime = QDateTime::currentDateTime();
    
    // 发出统计信息更新信号
    emit statisticsChanged();
}

// 更新统计信息（用于状态栏显示）
void DataIO::updateStatistics()
{
    // 更新上次统计时间
    lastStatsUpdateTime = QDateTime::currentDateTime();
    lastReceivedBytesSnapshot = receivedBytesCount;
    
    // 发出统计信息更新信号
    emit statisticsChanged();
}

// 设置自动发送文本
void DataIO::setAutoSendText(const QString &text)
{
    autoSendText = text;
}

// 自动发送定时器超时处理
void DataIO::onAutoSendTimerTimeout()
{
    if (isAutoSend && !autoSendText.isEmpty()) {
        sendData(autoSendText, isHexSend);
    }
}

// 接收刷新定时器超时处理
void DataIO::onReceiveFlushTimerTimeout()
{
    if (!receiveDataBlocks.isEmpty() && !pauseReceiving) {
        flushReceiveBuffer();
    }
}

// 查找文本在接收缓冲区中
QList<int> DataIO::findTextInReceiveBuffer(const QString &text, bool caseSensitive)
{
    QList<int> lineNumbers;
    Qt::CaseSensitivity sensitivity = caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
    
    // 在每一行中查找文本
    for (int i = 0; i < receiveBufferLines.size(); ++i) {
        if (receiveBufferLines.at(i).contains(text, sensitivity)) {
            lineNumbers.append(i);
        }
    }
    
    return lineNumbers;
}

// 导出接收数据到文件
bool DataIO::exportReceiveDataToFile(const QString &filePath)
{
    QFile file(filePath);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        return false;
    }
    
    QTextStream out(&file);
    
    // 写入所有缓冲行
    for (const QString &line : receiveBufferLines) {
        out << line << "\n";
    }
    
    file.close();
    return true;
}

// 验证发送输入是否有效
bool DataIO::validateSendInput(const QString &input, bool isHex)
{
    if (input.isEmpty()) {
        return false;
    }
    
    if (isHex) {
        // 检查是否只包含有效的十六进制字符
        QRegularExpression hexRegex("^[0-9a-fA-F\\s]*$");
        return hexRegex.match(input).hasMatch();
    }
    
    // ASCII模式总是有效的
    return true;
}

bool DataIO::isReceiveBufferEmpty() const
{
    return receiveBufferLines.isEmpty();
}

QStringList DataIO::takeReceiveBufferLines()
{
    QStringList lines = receiveBufferLines;
    receiveBufferLines.clear();
    return lines;
}